package com.yb;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.SecureClassLoader;
import java.util.*;

public class SalaryJARLoader6 extends SecureClassLoader {
    private final String jarFile;

    public SalaryJARLoader6(String jarFile) {
        this.jarFile = jarFile;
    }

    @Override
    public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
        synchronized (getClassLoadingLock(name)) {
            // 1. 先看是否已经加载过
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                try {
                    // 2. 尝试自己加载
                    c = findClass(name);
                } catch (ClassNotFoundException e) {
                    // 3. 失败则交给父加载器
                    c = super.loadClass(name, resolve);
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

    @Override
    protected Class<?> findClass(String fullClassName) throws ClassNotFoundException {
        String classFilepath = fullClassName.replace('.', '/').concat(".class");
        try {
            URL jarURL = new URL("jar:file:" + jarFile + "!/" + classFilepath);
            URLConnection urlConnection = jarURL.openConnection();
            urlConnection.setUseCaches(false);
            try (InputStream is = urlConnection.getInputStream();
                 ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
                int code;
                while ((code = is.read()) != -1) {
                    bos.write(code);
                }
                byte[] data = bos.toByteArray();
                return defineClass(fullClassName, data, 0, data.length);
            }
        } catch (IOException e) {
            throw new ClassNotFoundException(fullClassName, e);
        }
    }

    /**
     * 让 ServiceLoader 能找到 SPI 配置文件
     */
    @Override
    public URL getResource(String name) {
        try {
            URL url = new URL("jar:file:" + jarFile + "!/" + name);
            URLConnection conn = url.openConnection();
            conn.setUseCaches(false);
            try (InputStream ignored = conn.getInputStream()) {
                // 能打开说明存在
                return url;
            }
        } catch (Exception e) {
            return super.getResource(name);
        }
    }

    @Override
    public Enumeration<URL> getResources(String name) throws IOException {
        List<URL> urls = new ArrayList<>();
        URL res = getResource(name);
        if (res != null) {
            urls.add(res);
        }
        Enumeration<URL> parent = getParent().getResources(name);
        while (parent.hasMoreElements()) {
            urls.add(parent.nextElement());
        }
        return Collections.enumeration(urls);
    }
}


